﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Quickly.Certs.Core;
using Quickly.Certs.EntityFrameworkCore.Data;

namespace Quickly.Certs.EntityFrameworkCore
{
    public static class EntityFrameworkCoreBuilderExtensions
    {
        public static void ConfigureDatabase(IServiceProvider serviceProvider, DbContextOptionsBuilder builder, string? connectionName)
        {
            var configuration = serviceProvider.GetService<IConfiguration?>();
            var databaseOption = serviceProvider.GetService<IOptions<DatabaseOption>>()?.Value;
            var connectionString = configuration?.GetConnectionString(databaseOption?.ConnectionName ?? connectionName ?? "Default");

            switch (databaseOption?.Type)
            {
                case DatabaseType.Sqlite:
                    builder.UseSqlite(connectionString, options =>
                    {
                        options.MigrationsAssembly("Quickly.Certs.SqliteMigrations");
                        options.MigrationsHistoryTable("__EFMigrationHistories");
                    });

                    break;
                case DatabaseType.Postgres:
                    builder.UseNpgsql(connectionString, options =>
                    {
                        options.MigrationsAssembly("Quickly.Certs.PostgresMigrations");
                        options.MigrationsHistoryTable("__EFMigrationHistories");
                    });

                    break;
                default:
                    throw new InvalidOperationException($"不支持的数据库类型: '{databaseOption?.Type}', 当前支持: 'sqlite','postgres'");
            }
        }

        public static Action<IServiceProvider, DbContextOptionsBuilder> BuildConfigureDatabase(string connectionName) => (IServiceProvider serviceProvider, DbContextOptionsBuilder builder) => ConfigureDatabase(serviceProvider, builder, connectionName);

        public static IServiceCollection AddDbContextConfigurationQuickly<T>(this IServiceCollection services, string connectionName) where T : DbContext
        {
            services.AddTransient<IConfigureOptions<DatabaseOption>>(sp =>
            {
                var config = sp.GetService<IConfiguration?>();

                return new ConfigureOptions<DatabaseOption>(options => config?.Bind("Database", options));
            });

            services.AddDbContext<T>(BuildConfigureDatabase(connectionName));

            return services;
        }

        public static IServiceCollection AddDbContextQuickly<T>(this IServiceCollection services, string connectionName) where T : DbContext
        {
            services.AddDbContextConfigurationQuickly<T>(connectionName);

            services.AddScoped<IDomainNameStore, DomainNameStore>();
            services.AddScoped<ICertificateDataStore, CertificateDataStore>();
            services.AddScoped<IDatabaseAccountRepository, DatabaseAccountRepository>();

            return services;
        }
    }
}
